﻿package com.designoutput.ui.newControls
{
    import com.designoutput.enum.Direction;
    import com.designoutput.event.ScrollEvent;
    import com.designoutput.icon.ScrollbarDown;
    import com.designoutput.icon.ScrollbarHdrgGrip;
    import com.designoutput.icon.ScrollbarHdrgLeft;
    import com.designoutput.icon.ScrollbarHdrgMiddle;
    import com.designoutput.icon.ScrollbarHdrgRight;
    import com.designoutput.icon.ScrollbarLeft;
    import com.designoutput.icon.ScrollbarRight;
    import com.designoutput.icon.ScrollbarUp;
    import com.designoutput.icon.ScrollbarVdrgBottom;
    import com.designoutput.icon.ScrollbarVdrgGrip;
    import com.designoutput.icon.ScrollbarVdrgMiddle;
    import com.designoutput.icon.ScrollbarVdrgTop;
    
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;

    public class Scrollbar extends Sprite
    {
		protected var _type:Direction;
        private var _size:int = 0;
		private var _contentSize:int = 0;
		protected var _viewPortSize:int = 0;
		
        private var _background:Sprite;
		
        private var _startButton:Sprite;
		private var _endButton:Sprite;
        
        private var _drag:Sprite;
		private var _dragGrip:Bitmap;
		private var _dragStart:Bitmap;
		private var _dragMiddle:Bitmap;
		private var _dragEnd:Bitmap;
		
        private var _scrollAmount:int = 0;
		
        public function Scrollbar(type:Direction)
        {
            _type = type;
			
			if (type == Direction.Vertical)
				createChildrenVertical();
			else
				createChildrenHorizontal();
		}
		
		private function createChildrenHorizontal():void
		{
			_background = new Sprite();
			_background.graphics.beginFill(14211289);
			_background.graphics.drawRect(0, 0, 16, 16);
			_background.graphics.endFill();
			_background.width = _size;
			addChild(_background);
			
			_startButton = new Sprite();
			_startButton.addChild(new Bitmap(new ScrollbarLeft(0, 0)));
			_startButton.addEventListener(MouseEvent.MOUSE_DOWN, startButton_mouseDownHandler);
			_startButton.y = 1;
			_startButton.x = 1;
			addChild(_startButton);
			
			_endButton = new Sprite();
			_endButton.addChild(new Bitmap(new ScrollbarRight(0, 0)));
			_endButton.addEventListener(MouseEvent.MOUSE_DOWN, endButton_mouseDownHandler);
			_endButton.y = 1;
			_endButton.x = _size - 15;
			addChild(_endButton);
			
			_drag = new Sprite();
			_drag.addEventListener(MouseEvent.MOUSE_DOWN, dragMouseDown);
			_drag.y = 1;
			_drag.x = 16;
			
			_dragStart = new Bitmap(new ScrollbarHdrgLeft(0, 0));
			_drag.addChild(_dragStart);
			
			_dragMiddle = new Bitmap(new ScrollbarHdrgMiddle(0, 0));
			_dragMiddle.x = 5;
			_drag.addChild(_dragMiddle);
			
			_dragEnd = new Bitmap(new ScrollbarHdrgRight(0, 0));
			_drag.addChild(_dragEnd);
			
			_dragGrip = new Bitmap(new ScrollbarHdrgGrip(0, 0));
			_drag.addChild(_dragGrip);
			addChild(_drag);
			
			update();
		}
		
		private function createChildrenVertical():void
		{
			_background = new Sprite();
			_background.graphics.beginFill(14211289);
			_background.graphics.drawRect(0, 0, 16, 16);
			_background.graphics.endFill();
			_background.height = _size;
			addChild(_background);
			
			_startButton = new Sprite();
			_startButton.addChild(new Bitmap(new ScrollbarUp(0, 0)));
			_startButton.addEventListener(MouseEvent.MOUSE_DOWN, startButton_mouseDownHandler);
			_startButton.x = 1;
			_startButton.y = 1;
			addChild(_startButton);
			
			_endButton = new Sprite();
			_endButton.addChild(new Bitmap(new ScrollbarDown(0, 0)));
			_endButton.addEventListener(MouseEvent.MOUSE_DOWN, endButton_mouseDownHandler);
			_endButton.x = 1;
			addChild(_endButton);
			
			
			_drag = new Sprite();
			_drag.addEventListener(MouseEvent.MOUSE_DOWN, dragMouseDown);
			_drag.x = 1;
			_drag.y = 16;
			addChild(_drag);
			
			_dragStart = new Bitmap(new ScrollbarVdrgTop(0, 0));
			_drag.addChild(_dragStart);
			
			_dragMiddle = new Bitmap(new ScrollbarVdrgMiddle(0, 0));
			_dragMiddle.y = 5;
			_drag.addChild(_dragMiddle);
			
			_dragEnd = new Bitmap(new ScrollbarVdrgBottom(0, 0));
			_drag.addChild(_dragEnd);
			
			_dragGrip = new Bitmap(new ScrollbarVdrgGrip(0, 0));
			_drag.addChild(_dragGrip);
			
			update();
		}
		
		private function resizeDrag(dragSize:int):void {
			if(_type == Direction.Vertical){
				_dragMiddle.height = int(dragSize - _dragEnd.height - _dragMiddle.y);
				_dragGrip.x = 5;
				_dragGrip.y = int(dragSize/2 - (_dragGrip.height / 2));
				_dragEnd.y = int(dragSize - _dragEnd.height);
			} else {
				_dragMiddle.width = int(dragSize - _dragEnd.width - _dragMiddle.x);
				_dragGrip.x = int(dragSize/2 - (_dragGrip.width / 2));
				_dragGrip.y = 5;
				_dragEnd.x = int(dragSize - _dragEnd.width);
			}
		}
		
		public function get scrollAmount():int {
			return _scrollAmount;
		}
		
		public function set scrollAmount(value:int):void
		{
			_scrollAmount = value;
			update();
			dispatchEvent(new ScrollEvent(ScrollEvent.SCROLL, _scrollAmount));
		}
		
		public function get viewportSize():int {
			return _viewPortSize;
		}
		
		public function set viewportSize(value:int):void
		{
			_viewPortSize = value;
			update();
		}
		
		public function get size():int {
			return _size;
		}
		
		public function set size(value:int):void
		{
			_size = value;
			update();
		}
		
		public function get contentSize():int {
			return _contentSize;
		}
		
		public function set contentSize(value:int):void
		{
			_contentSize = value;
			update();
		}
		
		protected function get contentMaxScroll():int {
			return _contentSize - _viewPortSize;
		}
		
		protected function get myMaxScroll():int {
			if(_type == Direction.Vertical)
				return _size - 32 - _drag.height;
			else
				return _size - 32 - _drag.width;
		}
		
		protected function get myScrollArea():int {
			return _size - 32;
		}
		
		private function update():void
		{
			if(_scrollAmount > contentMaxScroll && _scrollAmount > 0)
				_scrollAmount = contentMaxScroll;
			if(_scrollAmount < 0)
				_scrollAmount = 0;
			
			var showScrollbars:Boolean = _contentSize > _viewPortSize;
			
			_startButton.visible = showScrollbars;
			_endButton.visible = showScrollbars;
			_drag.visible = showScrollbars;
			
			if(showScrollbars)
			{
				if(_type == Direction.Vertical) {
					resizeDrag(Math.max((_viewPortSize / _contentSize) * myScrollArea, 8));
					_endButton.y = _size - 15;
					_drag.y = (_scrollAmount / contentMaxScroll) * myMaxScroll + 16;
				} else {
					resizeDrag(Math.max((_viewPortSize / _contentSize) * myScrollArea, 8));
					_endButton.x = _size - 15;
					_drag.x = (_scrollAmount / contentMaxScroll) * myMaxScroll + 16;
				}
			}
			
			if(_type == Direction.Vertical)
				_background.height = _size;
			else
				_background.width = _size;
		}
		
		protected function startButton_mouseDownHandler(event:MouseEvent):void
		{
			scrollAmount -= 20;
		}
		
		protected function endButton_mouseDownHandler(event:MouseEvent):void
		{
			scrollAmount += 20;
		}
		
        private function updateScrollFromDragPosition(event:Event = null):void
        {
			var newScrollAmount:int;
			
			if(_type == Direction.Vertical)
				newScrollAmount = (_drag.y - 16) / myMaxScroll * contentMaxScroll;
			else
				newScrollAmount = (_drag.x - 16) / myMaxScroll * contentMaxScroll;
			
			scrollAmount = Math.round(newScrollAmount);
        }

		protected function dragMouseDown(event:MouseEvent):void
        {
			var dragRectangle:Rectangle;
			
            if (_type == Direction.Vertical)
				dragRectangle = new Rectangle(1, 16, 0, myMaxScroll)
            else
				dragRectangle = new Rectangle(16, 1, myMaxScroll, 0);
			
			_drag.startDrag(false, dragRectangle);

            addEventListener(Event.ENTER_FRAME, updateScrollFromDragPosition);
            stage.addEventListener(MouseEvent.MOUSE_UP, dragMouseUp, false, 0, true);
        }

		protected function dragMouseUp(event:MouseEvent):void
        {
            _drag.stopDrag();
            removeEventListener(Event.ENTER_FRAME, updateScrollFromDragPosition);
            stage.removeEventListener(MouseEvent.MOUSE_UP, dragMouseUp, false);
        }
    }
}